package com.ndp.fb.mq.consumer.business.syncbusiness;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ndp.fb.config.ConfigCentre;
import com.ndp.fb.constant.ConfigConst;
import com.ndp.fb.enums.adgroupstatus.AdGroupStatus;
import com.ndp.fb.fbagent.service.AdCampaignGroupFBService;
import com.ndp.fb.fbagent.service.AdGroupFBService;
import com.ndp.fb.model.fbagent.param.APIPriority;
import com.ndp.fb.model.fbagent.param.ApiCallBackTarget;
import com.ndp.fb.model.fbagent.param.adcampaigngroups.AdCampaignParam;
import com.ndp.fb.model.fbagent.param.adgroup.AdGroupParam;
import com.ndp.fb.mongo.api.AdGroupMongoService;
import com.ndp.fb.mongo.api.AdGroupStatsMongoService;
import com.ndp.fb.mq.api.service.schedulerservice.AdAccountsSchedulerService;
import com.ndp.fb.rdb.api.AdCampaignRdbService;
import com.ndp.fb.rdb.api.AdRdbService;
import com.ndp.fb.rdb.model.AdGroup;
import com.ndp.fb.redis.api.RedisClient;
import com.ndp.fb.util.DateUtil;
import com.ndp.fb.util.ListUtil;
import com.ndp.fb.util.StringUtil;
import com.restfb.json.JsonArray;
import com.restfb.json.JsonObject;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by jacky.cheng on 2015/6/18.
 */
@Component
public class AdGroupGCBusiness {

    private Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    private AdAccountsSchedulerService adaccountsSchedulerService;

    @Autowired
    private RedisClient redisClient;

    @Reference
    private AdGroupFBService adGroupFBService;

    @Reference
    private AdCampaignGroupFBService adCampaignGroupFBService;

    @Reference
    private AdGroupMongoService adGroupMongoService;

    @Reference
    private AdCampaignRdbService adCampaignGroupRdbService;

    @Reference
    private AdRdbService adGroupRdbService;

    @Reference
    private AdGroupStatsMongoService adGroupStatsMongoService;


    public void fetchOneCallBack(String body, Map<String, String> equipment) {
        JSONObject adJson = JSON.parseObject(body);
        AdGroup ad = getAdGroup(adJson);
        if (ad.getAdGroupStatus().equalsIgnoreCase(AdGroupStatus.ARCHIVED.getStatus())) {
            //ARCHIVED 状态大于7天，则置为 DELETED。
            if ((System.currentTimeMillis() - ad.getUpdatedUtcTime()) > (ConfigCentre.getInteger(ConfigConst.AD_ARCHIVED_DAYS) == 0 ? 7 : ConfigCentre.getInteger(ConfigConst.AD_ARCHIVED_DAYS))  * 3600000) {
                logger.info("ARCHIVED 状态大于7天，置为DELETED。adGroupId:{}", ad.getAdGroupId());
                //update ad status to DELETED.
                AdGroupParam param = new AdGroupParam();
                param.setAdGroupId(ad.getAdGroupId().toString());
//                param.setAdgroupStatus(AdGroupStatus.DELETED.getStatus());
                param.setStatus(AdGroupStatus.DELETED.getStatus());
                param.setFbAccountId(ad.getFbAccountId());
                param.setCallBack(true);
                param.setApiCallbackTargetType(ApiCallBackTarget.AutoControl.AdGroupDelete.getTargetType());
                param.setEquipment(equipment);
                equipment.put("adGroup", JSON.toJSONString(ad));
                param.setApiPriorityCode(APIPriority.PauseAdGroup.getCode());
                adGroupFBService.updateAdGroup(equipment.get("accessToken"), ad.getFbAccountId(), param);
            } else {
                //do nothing
                logger.info("ARCHIVED 状态小于7天，不回收，adGroupId:{}", ad.getAdGroupId());
            }
        }
        if (ad.getAdGroupStatus().equalsIgnoreCase(AdGroupStatus.DELETED.getStatus())) {
            logger.info("已经是DELETED状态，回收ad，adGroupId:{}", ad.getAdGroupId());
            try {
                doGC(ad);
            } catch (Exception e) {
                logger.error("回收ad失败，adGroupId:{}", ad.getAdGroupId(), e);
                e.printStackTrace();
            }
        }
    }

    /**
     * add by evan 2015-08-25
     * 删除广告 从BOSS系统过来的
     */
    public void deleteAdFromBoss(Map<String, String> equipment)
    {
        logger.info("BOSS过来更新广告信息 deleteAdFromBoss（）" + JSON.toJSONString(equipment));
        if(equipment.size() == 0)
        {
            return;
        }
        Long fbAccountId = Long.parseLong(equipment.get("fbAccountId"));
        String beginTime = equipment.get("beginTime");
        String endTime = equipment.get("endTime");
        String adGroupStatus = equipment.get("adGroupStatus");
        String fbConnObjId = equipment.get("fbConnObjId");
        String token = adaccountsSchedulerService.getAdaccountsToken(fbAccountId);
        if (StringUtils.isEmpty(token)) {
            logger.error("deleteAdFromBoss>>>>>>账号:" + fbAccountId + "没有找到fbUser");
            return;
        }

        //是暂停  则暂停其父级所有的营销活动
        if(AdGroupStatus.PAUSED.getStatus().equals(adGroupStatus))
        {
            List<Long> adCampaignGroupIdList;
            if(StringUtil.isEmpty(beginTime) && StringUtil.isEmpty(fbConnObjId))
            {
                adCampaignGroupIdList = adCampaignGroupRdbService.findByFbAccountIdToPause(fbAccountId);  //找出广告账号下的营销活动
            }
            else if(StringUtil.isEmpty(beginTime) && StringUtil.isNotEmpty(fbConnObjId))
            {
                adCampaignGroupIdList = adCampaignGroupRdbService.findByFbConnectObjectId(Long.parseLong(fbConnObjId));
            }
            else if(StringUtil.isNotEmpty(beginTime) && StringUtil.isNotEmpty(fbConnObjId))
            {
                adCampaignGroupIdList = adCampaignGroupRdbService.findByFbConnectObjectIdAndTime(Long.parseLong(fbConnObjId), beginTime, endTime);
            }
            else
            {
                adCampaignGroupIdList = adCampaignGroupRdbService.findByFbAccountIdAndTime(fbAccountId, beginTime, endTime);  //找出广告账号下的广告
            }

            if(ListUtil.isNotEmpty(adCampaignGroupIdList))
            {
                AdCampaignParam param = new AdCampaignParam();
                param.setApiPriorityCode(APIPriority.PauseAdGroup.getCode());
                param.setCallBack(false);
                param.setFbAccountId(fbAccountId);
                param.setStatus(adGroupStatus);
                param.setAccessToken(token);
                for(Long id : adCampaignGroupIdList)
                {
                    logger.info("BOSS过来-------去facebook更新营销活动{}的状态---------- 至 {} ", id, adGroupStatus);
                    param.setCampaignId(id + "");
                    adCampaignGroupFBService.updateStats(param);
                }
            }

        }
        else if(AdGroupStatus.DELETED.getStatus().equals(adGroupStatus))
        {
            List<Long> adGroupList;
            if(StringUtil.isEmpty(beginTime) && StringUtil.isEmpty(fbConnObjId))
            {
                adGroupList = adGroupRdbService.findByFbAccountId(fbAccountId);  //找出广告账号下的广告
            }
            else if(StringUtil.isEmpty(beginTime) && StringUtil.isNotEmpty(fbConnObjId))
            {
                adGroupList = adGroupRdbService.findByFbConnectObjectId(Long.parseLong(fbConnObjId));
            }
            else if(StringUtil.isNotEmpty(beginTime) && StringUtil.isNotEmpty(fbConnObjId))
            {
                adGroupList = adGroupRdbService.findByFbConnectObjectIdAndTime(Long.parseLong(fbConnObjId), beginTime, endTime);
            }
            else
            {
                adGroupList = adGroupRdbService.findByFbAccountIdAndTime(fbAccountId, beginTime, endTime);  //找出广告账号下的广告
            }
            if(ListUtil.isNotEmpty(adGroupList))
            {
                //TODO adgroup本身是DELETED状态  只能改name  update adgroup_status会造成访问facebook报错
                AdGroupParam adGroupParam = new AdGroupParam();
                adGroupParam.setApiPriorityCode(APIPriority.PauseAdGroup.getCode());
                adGroupParam.setCallBack(false);
                adGroupParam.setFbAccountId(fbAccountId);
                adGroupParam.setStatus(adGroupStatus);
                adGroupParam.setAccessToken(token);

                for(Long adGroupId : adGroupList)
                {
                    logger.info("BOSS过来去facebook更新广告{}状态 至 {} ", adGroupId, adGroupStatus);
                    adGroupParam.setAdGroupId(adGroupId + "");
                    adGroupFBService.updateAdGroupStatsAsyn(adGroupParam);
                }
            }
        }
    }

    /**
     * add by evan 2015-08-25
     * 回收广告 从BOSS系统过来的
     */
    public void gcAdFromBoss(Object body)
    {
        logger.info("开始回收广告gcAdFromBoss>>>>>>账号:" + body.toString());
        Long fbAccountId = (Long)body;
        String token = adaccountsSchedulerService.getAdaccountsToken(fbAccountId);
        if (StringUtils.isEmpty(token)) {
            logger.error("gcAdFromBoss>>>>>>账号:" + fbAccountId + "没有找到fbUser");
            return;
        }
        String fields = "id,adgroup_status,updated_time";
        Map<String, String> equipment = new HashMap<>();
        equipment.put("entrustAccountId", fbAccountId + "");
        equipment.put("accessToken", token);
        AdGroupParam requestParam = new AdGroupParam();
        requestParam.setFields(fields);
        requestParam.setApiPriorityCode(APIPriority.FetchAdgroupBusiness.getCode());
        requestParam.setEquipment(equipment);
        requestParam.setApiCallbackTargetType(ApiCallBackTarget.Business.GcAdGroupCallback.getTargetType());
        requestParam.setCallBack(true);
        requestParam.setFbAccountId(fbAccountId);
        requestParam.setAccessToken(token);
        requestParam.setLimit(5000);

        //requestParam.setResultClassName(FbAdgroup.class.getName());
        adGroupFBService.getAdGroupByAccount(requestParam);
    }

    /**
     * add by evan 2015-08-25
     * 回收广告 从BOSS系统过来的 --->facebook回来   //ARCHIVED 状态大于7天
     */
    public void gcAdFromBossCallback(Object body)
    {
        logger.info("回收广告回来判定gcAdFromBossCallback>>>>>>");
        Map messageBodyMap = (Map) redisClient.get(body.toString());
        JsonObject jsonObject = new JsonObject(messageBodyMap.get("body").toString());
        Map<String, String> equipmentMap = (Map<String, String>) messageBodyMap.get("equipment");
        redisClient.delete(body.toString());
        if (jsonObject.has("error")) {
           return;
        } else if (jsonObject.has("data")) {

            Long fbAccountId = Long.parseLong(equipmentMap.get("entrustAccountId"));
            String token = equipmentMap.get("accessToken");
            JsonArray jsonSummary = jsonObject.getJsonArray("data");
            if(jsonSummary.length() == 0)
            {
                return;
            }
            else
            {
                AdGroupParam adGroupParam;
                JSONObject fbObject;     //获取的单个广告 对象
                Long adGroupId;          //广告id
                String adGroupStatus;    //状态
                long updateTime;         //最近一次操作时间
                for (int i = 0; i < jsonSummary.length(); i++) {
                    fbObject = JSONObject.parseObject(jsonSummary.get(i).toString());
                    adGroupId = Long.parseLong(fbObject.get("id").toString());
                    adGroupStatus = fbObject.get("adgroup_status").toString();
                    updateTime = DateUtil.FbDateToJavaDate(fbObject.get("updated_time").toString()).getTimeInMillis();
                    logger.info("回收广告回来判定广告id--"+adGroupId+"--状态--"+adGroupStatus+"--更新时间--"+updateTime);
                    if (adGroupStatus.equalsIgnoreCase(AdGroupStatus.ARCHIVED.getStatus())) {
                        if ((System.currentTimeMillis() - updateTime) > (ConfigCentre.getInteger(ConfigConst.AD_ARCHIVED_DAYS) == 0 ? 7 : ConfigCentre.getInteger(ConfigConst.AD_ARCHIVED_DAYS))  * 3600000) {
                            logger.info("ARCHIVED状态大于7天，置为DELETED。adGroupId:{}", adGroupId);
                            adGroupParam = new AdGroupParam();
                            adGroupParam.setApiPriorityCode(APIPriority.PauseAdGroup.getCode());
                            adGroupParam.setCallBack(false);
                            adGroupParam.setFbAccountId(fbAccountId);
                            adGroupParam.setStatus(AdGroupStatus.DELETED.getStatus());
                            adGroupParam.setAccessToken(token);
                            adGroupParam.setAdGroupId(adGroupId + "");

                            adGroupFBService.updateAdGroupStatsAsyn(adGroupParam);
                            adGroupRdbService.updateAdGroupStatus(adGroupId, AdGroupStatus.DELETED.getStatus());
                        }
                    }
                    else if (adGroupStatus.equalsIgnoreCase(AdGroupStatus.DELETED.getStatus())) {
                        logger.info("已经是DELETED状态，回收ad，adGroupId:{}", adGroupId);
                        adGroupRdbService.updateAdGroupStatus(adGroupId, AdGroupStatus.DELETED.getStatus());
                    }

                }
            }
            JsonObject pageJsonObject = jsonObject.getJsonObject("paging");
            //如果有下一页
            if(pageJsonObject.has("next"))
            {
                JsonObject after = pageJsonObject.getJsonObject("cursors");
                String fields = "id,adgroup_status,updated_time";
                Map<String, String> equipment = new HashMap<>();
                equipment.put("entrustAccountId", fbAccountId + "");
                equipment.put("accessToken", token);
                AdGroupParam requestParam = new AdGroupParam();
                requestParam.setFields(fields);
                requestParam.setApiPriorityCode(APIPriority.FetchAdgroupBusiness.getCode());
                requestParam.setEquipment(equipment);
                requestParam.setApiCallbackTargetType(ApiCallBackTarget.Business.GcAdGroupCallback.getTargetType());
                requestParam.setCallBack(true);
                requestParam.setFbAccountId(fbAccountId);
                requestParam.setAccessToken(token);
                requestParam.setLimit(5000);
                requestParam.setAfter(after.get("after").toString());

                adGroupFBService.getAdGroupByAccount(requestParam);

            }
        }
    }

    private void doGC(AdGroup ad) {
        //add to mongo
        adGroupMongoService.save(ad);
    }

    private AdGroup getAdGroup(JSONObject objMap) {
        AdGroup adGroup = new AdGroup();
        adGroup.setFbAccountId(objMap.getLong("account_id"));
        adGroup.setAdGroupId(objMap.getLong("id"));
        adGroup.setAdGroupStatus(objMap.getString("adgroup_status"));
        adGroup.setBidInfo(objMap.getString("bid_info"));
        adGroup.setBidType(objMap.getString("bid_type"));
        adGroup.setAdSetId(objMap.getLong("campaign_id"));
        adGroup.setCampaignGroupId(objMap.getLong("campaign_group_id"));
        adGroup.setConversionSpecs(objMap.getString("conversion_specs"));
        adGroup.setAdCreativeId(getCreativeId(objMap.getString("creative")));
        adGroup.setName(objMap.getString("name"));
        adGroup.setTrackingSpecs(objMap.getString("tracking_specs"));
        adGroup.setObjective(objMap.getString("objective"));
        adGroup.setTargeting(objMap.getString("targeting"));
        //生成时间
        Calendar cCreateTime = DateUtil.FbDateToJavaDate(objMap.getString("created_time"));
        Calendar cUpdateTime = DateUtil.FbDateToJavaDate(objMap.getString("updated_time"));

        adGroup.setCreatedTime(null == cCreateTime ? null : cCreateTime.getTime());
        adGroup.setUpdatedTime(cUpdateTime == null ? null : cUpdateTime.getTime());
        adGroup.setCreatedUtcTime(cCreateTime == null ? null : cCreateTime.getTimeInMillis());
        adGroup.setUpdatedUtcTime(cUpdateTime == null ? null : cUpdateTime.getTimeInMillis());
        //解析fbAppId入库
        String fbAppId = parseFbAppId(objMap.getString("conversion_specs"), objMap.getString("tracking_specs"));
        if (StringUtils.isNotEmpty(fbAppId)) {
            adGroup.setFbConnectionObjectId(Long.parseLong(fbAppId));
        } else {
            adGroup.setFbConnectionObjectId(0L);
        }
        adGroup.setProductConfId(0L);
        adGroup.setPublishBatchId(-1L);
        return adGroup;
    }

    /**
     * @param creative
     * @return Long creativeId
     * @discription 获取CreativeId
     * @author Administrator
     * 创建时间 2014年6月26日 上午12:14:39
     */
    private Long getCreativeId(String creative) {
        if (StringUtils.isEmpty(creative)) {
            return null;
        }
        return JSON.parseObject(creative).getLong("id");
    }

    /**
     * parseFbAppId
     *
     * @param conversionSpecs conversionSpecs
     * @param trackingSpecs   trackingSpecs
     * @return fbAppId
     */
    private String parseFbAppId(String conversionSpecs, String trackingSpecs) {
        String fbAppId = parseFbAppIdBySpec(conversionSpecs);
        if (null == fbAppId) {
            fbAppId = parseFbAppIdBySpec(trackingSpecs);
        }
        return fbAppId;
    }

    private String parseFbAppIdBySpec(String conversionSpecs) {
        if (StringUtils.isEmpty(conversionSpecs)) {
            return null;
        }
        JSONArray jsonArray = JSON.parseArray(conversionSpecs);
        String appid = null;
        for (int i = 0; i < jsonArray.size(); i++) {
            JSONObject jsonObject = jsonArray.getJSONObject(i);
            JSONArray appids = jsonObject.getJSONArray("application");

            if (appids != null && appids.size() > 0) {
                appid = appids.getString(0);
            }
            if (StringUtils.isNotEmpty(appid)) {
                break;
            }
        }
        return appid;
    }

}
